package opmq

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"io/fs"
	"path/filepath"
	"strings"
)

func rootHttp(c *gin.Context) {
	res := &JsonData{Topic_ClientIds: make(map[string][]string)}
	filepath.Walk("topicFlag", func(path string, info fs.FileInfo, err error) error {
		// a simple windows eg: walk path: topicFlag\a\a.txt  infoName: a.txt
		if info.IsDir() {
			return nil
		}
		topicName := strings.ReplaceAll(strings.ReplaceAll(filepath.Dir(path), `\`, `/`), `topicFlag/`, "")

		res.Topic_ClientIds[topicName] = append(res.Topic_ClientIds[topicName], info.Name())
		return nil
	})

	c.JSON(200, res)
}

// V4clients 获取多个文章标签
// - 文档: https://docs.emqx.cn/enterprise/v4.3/advanced/http-api.html#%E5%AE%A2%E6%88%B7%E7%AB%AF
func V4clients(c *gin.Context) {
	defer func() {
		err := recover()
		if err != nil {
			PANIC.Println("可能是分页错误: ", err)
		}
	}()

	// 先获取所有数据
	bg := Broker.GetAllClientData()

	clientid := c.Query("clientid")
	if clientid != "" {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			if v.ClientId == clientid {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	username := c.Query("username")
	if username != "" {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			if v.UserName == username {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	zone := c.Query("zone")
	if zone != "" {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			if v.Zone == zone {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	ip_address := c.Query("ip_address")
	if ip_address != "" {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			if v.IpAddress == ip_address {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	//客户端当前连接状态，
	//可取值有：connected,idle,disconnected
	conn_state := c.Query("conn_state")
	if conn_state != "" {
		switch conn_state {
		case "connected":
			tmp := make([]*ClientsProperty, 0)
			for _, v := range bg {
				if v.Connected {
					tmp = append(tmp, v)
				}
			}

			// 更新
			bg = tmp
		case "idle":
			// todo: 空闲的定义
			DEBUG.Println("不支持")
		case "disconnected":
			tmp := make([]*ClientsProperty, 0)
			for _, v := range bg {
				if !v.Connected {
					tmp = append(tmp, v)
				}
			}

			// 更新
			bg = tmp
		}
	}

	clean_start := c.GetBool("clean_start")
	DEBUG.Println("不支持clean_start", clean_start)
	//客户端协议名称，
	//可取值有：MQTT,CoAP,LwM2M,MQTT-SN
	//proto_name := c.Query("proto_name")
	//proto_ver := c.Query("proto_ver")

	// 模糊查询部分
	_like_clientid := c.Query("_like_clientid")
	if _like_clientid != "" {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			if strings.Contains(v.ClientId, _like_clientid) {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	_like_username := c.Query("_like_username")
	if _like_username != "" {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			if strings.Contains(v.UserName, _like_username) {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	_gte_created_at := c.GetInt64("_gte_created_at")
	if _gte_created_at != 0 {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			ca, err := TimeStringToUnix(v.CreatedAt)
			if err != nil {
				continue
			}
			if _gte_created_at <= ca.Unix() {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	_lte_created_at := c.GetInt64("_lte_created_at")
	if _lte_created_at != 0 {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			ca, err := TimeStringToUnix(v.CreatedAt)
			if err != nil {
				continue
			}
			if _lte_created_at >= ca.Unix() {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}
	_gte_connected_at := c.GetInt64("_gte_connected_at")
	if _gte_connected_at != 0 {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			ca, err := TimeStringToUnix(v.CreatedAt)
			if err != nil {
				continue
			}
			if _gte_connected_at <= ca.Unix() {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}
	_lte_connected_at := c.GetInt64("_lte_connected_at")
	if _lte_connected_at != 0 {
		tmp := make([]*ClientsProperty, 0)
		for _, v := range bg {
			ca, err := TimeStringToUnix(v.CreatedAt)
			if err != nil {
				continue
			}
			if _lte_connected_at >= ca.Unix() {
				tmp = append(tmp, v)
			}
		}

		// 更新
		bg = tmp
	}

	// 分页
	_page := c.GetInt64("_page")
	if _page == 0 {
		_page = 1
	}
	_limit := c.GetInt64("limit")
	if _limit == 0 {
		_limit = 10000
	}
	count := len(bg)

	metaData := make(map[string]interface{})
	metaData["page"] = _page
	metaData["limit"] = _limit
	metaData["count"] = len(bg)

	start := (_page - 1) * _limit
	end := _page * _limit
	lastIdx := 0
	for i := start; i < end; i++ {
		if i == end || i >= int64(count-1) {
			lastIdx = int(i)
			break
		}
	}

	// 最后校验
	if start > int64(count-1) || lastIdx > count-1 || start < 0 || lastIdx < 0 || int(start) > lastIdx {
		DEBUG.Println("参数传输错误")
		DEBUG.Println(start, lastIdx+1)
		metaData["count"] = 0
		c.JSON(200, gin.H{
			"code": 0,
			"data": nil,
			"meta": metaData,
		})
	} else {
		metaData["count"] = len(bg[start : lastIdx+1])
		DEBUG.Println("最后角标: ", start, lastIdx+1)
		c.JSON(200, gin.H{
			"code": 0,
			"data": bg[start : lastIdx+1],
			"meta": metaData,
		})
	}
}

// ShowAccount godoc
// @Summary Show a account
// @Router /api/v4/card5 [get]
func apiMonitorCard4(c *gin.Context) {
	fmt.Println("zpi")
	c.String(200, "zpi")
}

// V4Subscriptions godoc
// @Summary 集群订阅信息
// @Description 自身节点包括其他节点数据
// @Success 200 {array} ClusterSelf
// @Router /api/v4/sub [get]
func V4Subscriptions(c *gin.Context)  {
	type data struct {
		// 节点唯一id
		Id string `json:"id"`

		ClusterNet *ClusterNet

		// 主节点标示
		IsMaster bool `json:"is_master"`

		// 如果当前是从节点，远程主节点Ip,对应的是master Mqtt地址
		RemoteMasterIp string `json:"remote_master_ip"`
		MasterRocPort  string `json:"master_roc_port"`

		Nodes []*ClusterNode
	}

	d := &data{
		Id:             Broker.ClusterSelf.Id,
		ClusterNet:     &ClusterNet{
			Ip:      Broker.ClusterSelf.ClusterNet.Ip,
			RpcPort: Broker.ClusterSelf.ClusterNet.RpcPort,
		},
		IsMaster:       Broker.ClusterSelf.IsMaster,
		RemoteMasterIp: Broker.ClusterSelf.RemoteMasterIp,
		MasterRocPort:  Broker.ClusterSelf.MasterRocPort,
		Nodes:          Broker.ClusterSelf.Nodes,
	}

	c.JSON(200, d)
}